package brickdestroyer.simulation;

import brickdestroyer.math.Vector2D;

/**
 * This class manages all the physics constants and variables
 * that used within the game.
 * <p>It offers the ability to distort some of them.
 * 
 * @author Momchil Atanasov
 */
public final class PhysicsManager {
    
    public static final float DISPLACEMENT_RATIO = 0.5f;
    
    public static final float MAX_OBJECT_SPEED = 35.0f;
    
    
    private final static float DEFAULT_SLIDE = 0.8f;
    
    private final static float DISTORTED_SLIDE = 0.1f;

    private final static int DISTORTED_SLIDE_TIMER = 400;

    private final static float DEFAULT_BOUNCE = 0.97f;
    
    private final static float DISTORTED_BOUNCE = 1.1f;

    private final static int DISTORTED_BOUNCE_TIMER = 140;

    private final static float DEFAULT_GRAVITY = 0.1f;
  
    private final static float DISTORTED_GRAVITY = - 0.1f;

    private final static int DISTORTED_GRAVITY_TIMER = 250;
    
    /* Physical constants */
    private float slideRatio = DEFAULT_SLIDE;
    
    private int slideTimer = 0;

    private float bounceRatio = DEFAULT_BOUNCE;
    
    private int bounceTimer = 0;

    private float gravityRatio = DEFAULT_GRAVITY;

    private int gravityTimer = 0;
    
    public PhysicsManager() {
        restoreAll();
    }

    /**
     * This method restores all physics constants and
     * variables.
     */
    public void restoreAll() {
        restoreSlide();
        restoreBounce();
        restoreGravity();
    }

    /**
     * This method restores the slide variable to
     * it's default.
     */
    public void restoreSlide() {
        slideTimer = 0;
        slideRatio = DEFAULT_SLIDE;
    }

    /**
     * This method distorts the slide variable.
     */
    public void distortSlide() {
        slideTimer = DISTORTED_SLIDE_TIMER;
        slideRatio = DISTORTED_SLIDE;
    }

    /**
     * This method restores the bounce variable
     * to it's default.
     */
    public void restoreBounce() {
        bounceTimer = 0;
        bounceRatio = DEFAULT_BOUNCE;
    }

    /**
     * This method distorts the bounce variable.
     */
    public void distortBounce() {
        bounceTimer = DISTORTED_BOUNCE_TIMER;
        bounceRatio = DISTORTED_BOUNCE;
    }

    /**
     * This method restores the gravity constant
     * to it's default.
     */
    public void restoreGravity() {
        gravityTimer = 0;
        gravityRatio = DEFAULT_GRAVITY;
    }

    /**
     * This method distorts the gravity constant.
     */
    public void distortGravity() {
        gravityTimer = DISTORTED_GRAVITY_TIMER;
        gravityRatio = DISTORTED_GRAVITY;
    }

    /**
     * This method updates the physics manager.
     * <p>It ticks all timers that mesure when
     * specific distortions must be restored.
     */
    public void update() {
        updateSlide();
        updateBounce();
        updateGravity();
    }

    private void updateSlide() {
        if (slideTimer > 0) {
            slideTimer--;
            if (slideTimer <= 0) {
                restoreSlide();
            }
        }
    }

    private void updateBounce() {
        if (bounceTimer > 0) {
            bounceTimer--;
            if (bounceTimer <= 0) {
                restoreBounce();
            }
        }
    }

    private void updateGravity() {
        if (gravityTimer > 0) {
            gravityTimer--;
            if (gravityTimer <= 0) {
                restoreGravity();
            }
        }
    }

    /**
     * This method returns the slide variable.
     * @return the slide variable
     */
    public float getSlide() {
        return slideRatio;
    }

    /**
     * This method returns the bounce variable.
     * @return the bounce variable
     */
    public float getBounce() {
        return bounceRatio;
    }

    /**
     * This method returns the gravity variable
     * in the form of a vector which represents a
     * gravity force acting on objects.
     * @return vector instance representing the
     * gravity force.
     */
    public Vector2D getGravity() {
        return new Vector2D(0.0f, gravityRatio);
    }
        
}
